#pragma once

#include <string>
#include <cstdint>
#include <vector>
#include <fstream>
#include <sys/stat.h>
#include "cppjieba/Jieba.hpp"
#include <boost/algorithm/string.hpp>

#include "HpcServer/Server/Logger.hpp"

using namespace std;
using namespace LogMudule;

const string DocLineSep = "\3"; // 文档中一行内容之中的分隔符

const char *const DICT_PATH = "./dict/jieba.dict.utf8";
const char *const HMM_PATH = "./dict/hmm_model.utf8";
const char *const USER_DICT_PATH = "./dict/user.dict.utf8";
const char *const IDF_PATH = "./dict/idf.utf8";
const char *const STOP_WORD_PATH = "./dict/stop_words.utf8";

// 这个模块是⼀个工具模块，主要提供HTTP协议模块所用到的⼀些工具函数
class means
{
public:
    // 读取一个文件中的所有内容
    static bool ReadFile(const string &filepath, string *buf)
    {
        // 以二进制方式打开文件，这样普适性更强
        ifstream file(filepath, ios::in | ios::binary);

        // 如果打开失败
        if (file.is_open() == false)
        {
            LOG(LogLevel::WARNING) << filepath << "打开失败";
            return false;
        }

        // 把读指针移动到文件最末尾
        file.seekg(0, file.end);

        // 计算文件大小
        uint64_t file_size = file.tellg();

        // 把读指针移动到文件最开头
        file.seekg(0, file.beg);

        // 确保Buf能存放文件的所有内容
        buf->resize(file_size);

        // 读取文件
        if (!file.read(&(buf->at(0)), file_size))
        {
            LOG(LogLevel::WARNING) << filepath << "读取失败";
            file.close();
            return false;
        }
        // 关闭文件
        file.close();
        return true;
    }
    // 向文件写入
    static bool WriteFile(const string &filepath, string &data)
    {
        // 以二进制方式打开文件，这样普适性更强
        ofstream ofs(filepath, ios::out | ios::binary);
        // 如果打开失败
        if (ofs.is_open() == false)
        {
            LOG(LogLevel::WARNING) << filepath << "打开失败";
            return false;
        }

        // 写入文件
        if (!ofs.write(data.c_str(), data.size()))
        {
            LOG(LogLevel::WARNING) << filepath << "写入失败";
            ofs.close();
            return false;
        }

        // 关闭文件
        ofs.close();
        return true;
    }
    static void CppjiebaCatStr(const string &str, vector<string> *words)
    {
        static cppjieba::Jieba jieba(DICT_PATH,
                              HMM_PATH,
                              USER_DICT_PATH,
                              IDF_PATH,
                              STOP_WORD_PATH);

        jieba.CutForSearch(str, *words);
    }
    // 根据分割符分割字符串将分割后的串放进veactor中，返回值是子串的个数
    static int SepStr(const string &str, const string &sep, vector<string> &arr)
    {
        // 分隔符的起始下标
        uint64_t pos = 0;
        // 查找的起始位置
        uint64_t start = 0;

        // 字符串大小
        uint64_t size = str.size();

        // 循环执行
        while ((pos = str.find(sep, start)) != string::npos && pos < size)
        {
            // start==pos就是找到了连续的分割符,不需要添加到结果
            if (start == pos)
            {
                // 更新一下
                start = pos + sep.size();
                continue;
            }
            // 找到了就分割,添加到结果
            arr.emplace_back(str.substr(start, pos - start));
            // 更新一下
            start = pos + sep.size();
        }
        // 如果start == size那么就会添加一个空串，没有意义
        if (start != size)
        {
            // 找不到分隔符了,就把str最后剩下的部分也放进arr中
            arr.emplace_back(str.substr(start));
        }
        return arr.size();
    }
};